home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
prog
/
pcl4p40.arj
/
XYPACKET.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1993-03-09
|
12KB
|
422 lines
(*********************************************)
(* *)
(* This program is donated to the Public *)
(* Domain by MarshallSoft Computing, Inc. *)
(* It is provided as an example of the use *)
(* of the Personal Communications Library. *)
(* *)
(*********************************************)
{ $DEFINE DEBUG}
{$I DEFINES.PAS}
unit xypacket;
interface
type BufferType = array[0..1023] of Byte;
Function TxPacket(Port:Integer;
PacketNbr:Word;
PacketSize:Word;
Var Buffer:BufferType;
NCGbyte:Byte):Boolean;
Function RxPacket(Port:Integer;
PacketNbr:Word;
Var PacketSize:Word;
Var Buffer:BufferType;
NCGbyte:Byte;
Var EOTflag:Boolean):Boolean;
Function RxStartup(Port:Integer;
Var NCGbyte:Byte):Boolean;
Function TxStartup(Port:Integer;
Var NCGbyte:Byte):Boolean;
Function TxEOT(Port:Integer):Boolean;
implementation
uses PCL4P,term_io,crc,hex_io,crt;
const MAXTRY = 3;
LIMIT = 20;
const SOH = $01;
STX = $02;
EOT = $04;
ACK = $06;
NAK = $15;
CAN = $18;
Function TxPacket(Port:Integer; (* Port # [0..3] *)
PacketNbr:Word; (* Packet # [0,1,2,...] *)
PacketSize:Word; (* Packet size [128,1024] *)
Var Buffer:BufferType; (* 1K character buffer *)
NCGbyte:Byte) (* NAK, 'C', or 'G' *)
: Boolean; (* successfull *)
Label 999;
Var
I : Integer;
Code : Integer;
CheckSum : Word;
Attempt : Word;
PacketType: Byte;
Begin
(* better be 128 or 1024 packet length *)
if PacketSize = 1024
then PacketType := STX
else PacketType := SOH;
PacketNbr := PacketNbr and $00ff;
(* make up to MAXTRY attempts to send this packet *)
for Attempt := 1 to MAXTRY do
begin
(* send SOH/STX *)
PutChar(Port,PacketType);
(* send packet # *)
PutChar(Port,PacketNbr);
(* send 1's complement of packet *)
PutChar(Port,255-PacketNbr);
(* send data *)
CheckSum := 0;
for i := 0 to PacketSize - 1 do
begin
PutChar(Port,Buffer[i]);
(* update checksum *)
if NCGbyte<>NAK then CheckSum := UpdateCRC(CheckSum, Buffer[i])
else CheckSum := CheckSum + Buffer[i];
end;
{$IFDEF DEBUG}
write('<Checksum=$');
WriteHexWord(CheckSum);
write('>');
{$ENDIF}
(* send checksum *)
if NCGbyte<>NAK then
begin
(* send 2 byte CRC *)
PutChar(Port, (CheckSum shr 8) and $00ff );
PutChar(Port, CheckSum and $00ff );
end
else (* NCGbyte = 'C' or 'G' *)
begin
(* send one byte checksum *)
PutChar(Port,CheckSum );
end;
(* don't wait for ACK if 'G' *)
if NCGbyte = Ord('G') then
begin
if PacketNbr = 0 then delay(SHORT_WAIT*ONE_SECOND div 2);
TxPacket := TRUE;
Goto 999
end;
(* wait for receivers ACK *)
Code := GetChar(Port,LONG_WAIT*ONE_SECOND);
if Code = CAN then
begin
WriteLn('Canceled by remote');
TxPacket := FALSE;
Goto 999;
end;
if Code = ACK then
begin
TxPacket := TRUE;
Goto 999
end;
if Code <> NAK then
begin
WriteLn('Out of sync');
TxPacket := FALSE;
Goto 999;
end;
end; (* end for *)
(* can't send packet ! *)
Writeln('Packet timeout for port ',Port);
TxPacket := FALSE;
999: end; (* end -- TxPacket *)
Function RxPacket(Port:Integer; (* Port # 0..3 *)
PacketNbr:Word; (* Packet # [0,1,2,...] *)
Var PacketSize:Word; (* Packet size (128 or 1024) *)
Var Buffer:BufferType; (* 1K buffer *)
NCGbyte:Byte; (* NAK, 'C', or 'G' *)
Var EOTflag:Boolean) (* EOT was received *)
:Boolean; (* success / failure *)
Label 999;
Var
I : Integer;
Code : Integer;
Attempt : Word;
RxPacketNbr : Word;
RxPacketNbrC : Word;
CheckSum : Word;
RxCheckSum : Word;
RxCheckSum1 : Word;
RxCheckSum2 : Word;
PacketType : Byte;
begin
PacketNbr := PacketNbr AND $00ff;
for Attempt := 1 to MAXTRY do
begin
(* wait for SOH / STX *)
Code := GetChar(Port,LONG_WAIT*ONE_SECOND);
if Code = -1 then
begin
WriteLn('Timed out waiting for sender');
RxPacket := FALSE;
Goto 999
end;
case Code of
SOH: begin
(* 128 byte buffer incoming *)
PacketType := SOH;
PacketSize := 128
end;
STX: begin
(* 1024 byte buffer incoming *)
PacketType := STX;
PacketSize := 1024;
end;
EOT: begin
(* all packets have been sent *)
PutChar(Port,ACK);
EOTflag := TRUE;
RxPacket := TRUE;
goto 999
end;
CAN: begin
(* sender has canceled ! *)
SayError(Port,'Canceled by remote');
RxPacket := FALSE;
end;
else
begin
(* error ! *)
Write('Expecting SOH/STX/EOT/CAN not $');
WriteHexByte(Code);
Writeln;
RxPacket := FALSE;
end;
end;
(* receive packet # *)
Code := GetChar(Port,ONE_SECOND);
if Code = -1 then
begin
WriteLn('timed out waiting for packet #');
goto 999;
end;
RxPacketNbr := $00ff and Code;
(* receive 1's complement *)
Code := GetChar(Port,ONE_SECOND);
if Code =-1 then
begin
WriteLn('timed out waiting for complement of packet #');
RxPacket := FALSE;
Goto 999
end;
RxPacketNbrC := $00ff and Code;
(* receive data *)
CheckSum := 0;
for i := 0 to PacketSize - 1 do
begin
Code := GetChar(Port,ONE_SECOND);
if Code = -1 then
begin
WriteLn('timed out waiting for data for packet #');
RxPacket := FALSE;
Goto 999
end;
Buffer[i] := Code;
(* compute CRC or checksum *)
if NCGbyte<>NAK
then CheckSum := UpdateCRC(CheckSum,Code)
else CheckSum := (CheckSum + Code) AND $00ff;
end;
(* receive CRC/checksum *)
if NCGbyte<>NAK then
begin
(* receive 2 byte CRC *)
Code := GetChar(Port,ONE_SECOND);
if Code =-1 then
begin
WriteLn('timed out waiting for 1st CRC byte');
RxPacket := FALSE;
Goto 999
end;
RxCheckSum1 := Code AND $00ff;
Code := GetChar(Port,ONE_SECOND);
if Code =-1 then
begin
WriteLn('timed out waiting for 2nd CRC byte');
RxPacket := FALSE;
Goto 999
end;
RxCheckSum2 := Code AND $00ff;
RxCheckSum := (RxCheckSum1 SHL 8) OR RxCheckSum2;
end
else
begin
(* receive one byte checksum *)
Code := GetChar(Port,ONE_SECOND);
if Code = -1 then
begin
WriteLn('timed out waiting for checksum');
RxPacket := FALSE;
Goto 999
end;
RxCheckSum := Code AND $00ff;
end;
{$IFDEF DEBUG}
write('<Checksum: Received=$');
WriteHexWord(RxCheckSum);
write(', Computed=$');
WriteHexWord(CheckSum);
write('>');
{$ENDIF}
(* don't send ACK if 'G' *)
if NCGbyte = Ord('G') then
begin
RxPacket := TRUE;
Goto 999
end;
(* packet # and checksum OK ? *)
if (RxCheckSum=CheckSum) and (RxPacketNbr=PacketNbr) then
begin
(* ACK the packet *)
PutChar(Port,ACK);
RxPacket := TRUE;
Goto 999
end;
(* bad packet *)
WriteMsg('Bad Packet',1);
PutChar(Port,NAK)
end;
(* can't receive packet *)
SayError(Port,'RX packet timeout');
RxPacket := FALSE;
999: end; (* end -- RxPacket *)
Function TxStartup(Port:Integer;
Var NCGbyte:Byte):Boolean;
Label 999;
Var
Code : Integer;
I : Integer;
Result : Boolean;
Begin
(* clear Rx buffer *)
Code := SioRxFlush(Port);
(* wait for receivers start up NAK or 'C' *)
for i := 1 to LIMIT do
begin
if KeyPressed then
begin
SayError(Port,'Aborted by user');
Result := FALSE;
Goto 999
end;
Code := GetChar(Port,SHORT_WAIT*ONE_SECOND);
if Code <> -1 then
begin
(* received a byte *)
if Code = NAK then
begin
NCGbyte := NAK;
Result := TRUE;
Goto 999
end;
if Code = Ord('C') then
begin
NCGbyte := Ord('C');
Result := TRUE;
Goto 999
end;
if Code = Ord('G') then
begin
NCGbyte := Ord('G');
Result := TRUE;
Goto 999
end
end
end;
(* no response *)
SayError(Port,'No response from receiver');
TxStartup := FALSE;
999:
TxStartup := Result;
{$IFDEF DEBUG}
write('<TxStartup ');
if Result then writeln('successfull>')
else writeln('fails>');
{$ENDIF}
end; (* end -- TxStartup *)
Function RxStartup(Port:Integer;
Var NCGbyte:Byte)
: Boolean;
Label 999;
Var
I : Integer;
Code : Integer;
Result : Boolean;
Begin
(* clear Rx buffer *)
Code := SioRxFlush(Port);
(* Send NAKs or 'C's *)
for I := 1 to LIMIT do
begin
if KeyPressed then
begin
SayError(Port,'Canceled by user');
Result := FALSE;
Goto 999
end;
(* stop attempting CRC after 1st 4 tries *)
if (NCGbyte<>NAK) and (i=5) then NCGbyte := NAK;
(* tell sender that I am ready to receive *)
PutChar(Port,NCGbyte);
Code := GetChar(Port,SHORT_WAIT*ONE_SECOND);
if Code <> -1 then
begin
(* no error -- must be incoming byte -- push byte back onto queue ! *)
Code := SioUnGetc(Port,Code);
Result := TRUE;
Goto 999
end;
end; (* for i *)
(* no response *)
SayError(Port,'No response from sender');
Result := FALSE;
999:
RxStartup := Result;
{$IFDEF DEBUG}
write('<RxStartup ');
if Result then writeln('successfull>')
else writeln('fails>');
{$ENDIF}
end; (* end -- RxStartup *)
Function TxEOT(Port:Integer):Boolean;
Label 999;
Var
I : Integer;
Code : Integer;
Begin
for I := 0 to 10 do
begin
PutChar(Port,EOT);
(* await response *)
Code := GetChar(Port,SHORT_WAIT*ONE_SECOND);
if Code = ACK then
begin
TxEOT := TRUE;
Goto 999
end
end; (* end -- for I) *)
TxEOT := FALSE;
999: end; (* end -- TxEOT *)
end.